using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using MatrixFramework.Keycloak.Abstractions.Services;
using Volo.Abp.Domain.Repositories;
using AuthService.Domain.Auth;
using Microsoft.Extensions.Options;
using AuthService.Options;
using System.Diagnostics;
using Microsoft.AspNetCore.Http;

namespace AuthService.HttpApi.Host.HealthChecks;

/// <summary>
/// 认证授权服务健康检查
/// </summary>
public class AuthServiceHealthCheck : IHealthCheck, ITransientDependency
{
    private readonly ILogger<AuthServiceHealthCheck> _logger;
    private readonly IKeycloakAdminService _keycloakAdminService;
    private readonly IRepository<AuthSession, Guid> _authSessionRepository;
    private readonly IOptions<AuthServiceOptions> _options;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public AuthServiceHealthCheck(
        ILogger<AuthServiceHealthCheck> logger,
        IKeycloakAdminService keycloakAdminService,
        IRepository<AuthSession, Guid> authSessionRepository,
        IOptions<AuthServiceOptions> options,
        IHttpContextAccessor httpContextAccessor)
    {
        _logger = logger;
        _keycloakAdminService = keycloakAdminService;
        _authSessionRepository = authSessionRepository;
        _options = options;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var data = new Dictionary<string, object>
        {
            ["service"] = "AuthService",
            ["version"] = "1.0.0",
            ["timestamp"] = DateTime.UtcNow
        };

        var stopWatch = Stopwatch.StartNew();

        try
        {
            _logger.LogDebug("开始认证授权服务健康检查");

            var checkTasks = new List<Task<(string name, HealthStatus status, string message, long elapsedMs)>>
            {
                CheckKeycloakConnectionAsync(cancellationToken),
                CheckDatabaseConnectionAsync(cancellationToken),
                CheckTokenServiceAsync(cancellationToken),
                CheckCacheServiceAsync(cancellationToken)
            };

            var results = await Task.WhenAll(checkTasks);
            stopWatch.Stop();

            data["totalElapsedMs"] = stopWatch.ElapsedMilliseconds;

            foreach (var result in results)
            {
                data[$"check_{result.name}_status"] = result.status.ToString();
                data[$"check_{result.name}_elapsedMs"] = result.elapsedMs;
                data[$"check_{result.name}_message"] = result.message;
            }

            var unhealthyCount = results.Count(r => r.status == HealthStatus.Unhealthy);
            var degradedCount = results.Count(r => r.status == HealthStatus.Degraded);

            if (unhealthyCount > 0)
            {
                var unhealthyChecks = results.Where(r => r.status == HealthStatus.Unhealthy).Select(r => r.name);
                return Task.FromResult(HealthCheckResult.Unhealthy(
                    $"认证授权服务异常: {string.Join(", ", unhealthyChecks)}",
                    data: data));
            }

            if (degradedCount > 0)
            {
                var degradedChecks = results.Where(r => r.status == HealthStatus.Degraded).Select(r => r.name);
                return Task.FromResult(HealthCheckResult.Degraded(
                    $"认证授权服务性能降级: {string.Join(", ", degradedChecks)}",
                    data: data));
            }

            _logger.LogInformation("认证授权服务健康检查完成，总耗时: {ElapsedMs}ms", stopWatch.ElapsedMilliseconds);

            return Task.FromResult(HealthCheckResult.Healthy("认证授权服务运行正常", data: data));
        }
        catch (Exception ex)
        {
            stopWatch.Stop();
            data["totalElapsedMs"] = stopWatch.ElapsedMilliseconds;
            data["error"] = ex.Message;
            data["stackTrace"] = ex.StackTrace;

            _logger.LogError(ex, "认证授权服务健康检查失败，耗时: {ElapsedMs}ms", stopWatch.ElapsedMilliseconds);
            return Task.FromResult(HealthCheckResult.Unhealthy("认证授权服务异常", ex, data));
        }
    }

    /// <summary>
    /// 检查Keycloak连接状态
    /// </summary>
    private async Task<(string name, HealthStatus status, string message, long elapsedMs)> CheckKeycloakConnectionAsync(CancellationToken cancellationToken)
    {
        var stopWatch = Stopwatch.StartNew();
        try
        {
            var testResult = await _keycloakAdminService.TestConnectionAsync(cancellationToken);
            stopWatch.Stop();

            if (testResult.IsSuccess && testResult.Data)
            {
                var serverInfo = await _keycloakAdminService.GetServerInfoAsync(cancellationToken);
                if (serverInfo.IsSuccess)
                {
                    return ("keycloak", HealthStatus.Healthy,
                        $"Keycloak连接正常，服务器版本: {serverInfo.Data?.Version ?? "未知"}",
                        stopWatch.ElapsedMilliseconds);
                }
                else
                {
                    return ("keycloak", HealthStatus.Healthy, "Keycloak连接正常但无法获取服务器信息",
                        stopWatch.ElapsedMilliseconds);
                }
            }
            else
            {
                return ("keycloak", HealthStatus.Unhealthy,
                    $"Keycloak连接失败: {testResult.Message ?? "未知错误"}",
                    stopWatch.ElapsedMilliseconds);
            }
        }
        catch (Exception ex)
        {
            stopWatch.Stop();
            _logger.LogWarning(ex, "Keycloak连接检查失败");
            return ("keycloak", HealthStatus.Unhealthy, $"Keycloak连接异常: {ex.Message}",
                stopWatch.ElapsedMilliseconds);
        }
    }

    /// <summary>
    /// 检查数据库连接状态
    /// </summary>
    private async Task<(string name, HealthStatus status, string message, long elapsedMs)> CheckDatabaseConnectionAsync(CancellationToken cancellationToken)
    {
        var stopWatch = Stopwatch.StartNew();
        try
        {
            // 尝试查询认证会话表来验证数据库连接
            var sessionCount = await _authSessionRepository.GetCountAsync(cancellationToken);
            stopWatch.Stop();

            return ("database", HealthStatus.Healthy,
                $"数据库连接正常，当前活跃会话数: {sessionCount}",
                stopWatch.ElapsedMilliseconds);
        }
        catch (Exception ex)
        {
            stopWatch.Stop();
            _logger.LogWarning(ex, "数据库连接检查失败");
            return ("database", HealthStatus.Unhealthy, $"数据库连接异常: {ex.Message}",
                stopWatch.ElapsedMilliseconds);
        }
    }

    /// <summary>
    /// 检查Token服务状态
    /// </summary>
    private async Task<(string name, HealthStatus status, string message, long elapsedMs)> CheckTokenServiceAsync(CancellationToken cancellationToken)
    {
        var stopWatch = Stopwatch.StartNew();
        try
        {
            // 检查JWT配置是否完整
            var jwtSecret = _options.Value.JwtSecretKey;
            var jwtIssuer = _options.Value.JwtIssuer;
            var jwtAudience = _options.Value.JwtAudience;

            if (string.IsNullOrEmpty(jwtSecret) || jwtSecret.Length < 32)
            {
                return ("token_service", HealthStatus.Unhealthy, "JWT密钥配置无效", stopWatch.ElapsedMilliseconds);
            }

            if (string.IsNullOrEmpty(jwtIssuer) || string.IsNullOrEmpty(jwtAudience))
            {
                return ("token_service", HealthStatus.Unhealthy, "JWT发行者或受众配置缺失", stopWatch.ElapsedMilliseconds);
            }

            stopWatch.Stop();
            return ("token_service", HealthStatus.Healthy, "Token服务配置正常", stopWatch.ElapsedMilliseconds);
        }
        catch (Exception ex)
        {
            stopWatch.Stop();
            _logger.LogWarning(ex, "Token服务检查失败");
            return ("token_service", HealthStatus.Unhealthy, $"Token服务异常: {ex.Message}",
                stopWatch.ElapsedMilliseconds);
        }
    }

    /// <summary>
    /// 检查缓存服务状态
    /// </summary>
    private async Task<(string name, HealthStatus status, string message, long elapsedMs)> CheckCacheServiceAsync(CancellationToken cancellationToken)
    {
        var stopWatch = Stopwatch.StartNew();
        try
        {
            // 检查当前HTTP上下文
            var httpContext = _httpContextAccessor.HttpContext;
            if (httpContext == null)
            {
                return ("cache_service", HealthStatus.Degraded, "HTTP上下文不可用（在非HTTP请求中正常）",
                    stopWatch.ElapsedMilliseconds);
            }

            // 检查缓存相关配置
            var accessTokenLifetime = _options.Value.AccessTokenLifetimeMinutes;
            var refreshTokenLifetime = _options.Value.RefreshTokenLifetimeMinutes;

            if (accessTokenLifetime <= 0 || refreshTokenLifetime <= 0)
            {
                return ("cache_service", HealthStatus.Unhealthy, "Token生命周期配置无效",
                    stopWatch.ElapsedMilliseconds);
            }

            stopWatch.Stop();
            return ("cache_service", HealthStatus.Healthy,
                $"缓存服务正常，访问令牌生命周期: {accessTokenLifetime}分钟，刷新令牌生命周期: {refreshTokenLifetime}分钟",
                stopWatch.ElapsedMilliseconds);
        }
        catch (Exception ex)
        {
            stopWatch.Stop();
            _logger.LogWarning(ex, "缓存服务检查失败");
            return ("cache_service", HealthStatus.Unhealthy, $"缓存服务异常: {ex.Message}",
                stopWatch.ElapsedMilliseconds);
        }
    }
}